
/**
 * Observer class that is attached to each observed
 * object. Once attached, the observer converts the target
 * object's property keys into getter/setters that
 * collect dependencies and dispatch updates.
 */
var Observer = function Observer (value) {
	
	this.value = value;
	this.dep = new Dep();
	this.vmCount = 0;

	def(value, '__ob__', this);

	if (Array.isArray(value)) {

		var augment = hasProto
			? protoAugment
			: copyAugment;

		augment(value, arrayMethods, arrayKeys);

		this.observeArray(value);

	} else {
		this.walk(value);
	}
};

/**
 * Walk through each property and convert them into
 * getter/setters. This method should only be called when
 * value type is Object.
 * Learn: 监听一个对象，逐个对属性进行监听
 */
Observer.prototype.walk = function walk (obj) {
	var keys = Object.keys(obj);
	for (var i = 0; i < keys.length; i++) {
		defineReactive(obj, keys[i]);
	}
};

/**
 * Observe a list of Array items.
 * Learn: 监听一个数组，遍历数组，再逐个对属性进行监听
 */
Observer.prototype.observeArray = function observeArray (items) {
	for (var i = 0, l = items.length; i < l; i++) {
		observe(items[i]);
	}
};


/**
 * Attempt to create an observer instance for a value,
 * returns the new observer if successfully observed,
 * or the existing observer if the value already has one.
 */
function observe (value, asRootData) {

	if (!isObject(value) || value instanceof VNode) {
		return
	}
	var ob;
	
	if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
		ob = value.__ob__;
	} else if (
		shouldObserve &&
		!isServerRendering() &&
		(Array.isArray(value) || isPlainObject(value)) &&
		Object.isExtensible(value) &&
		!value._isVue
	) {
		ob = new Observer(value);
	}
	if (asRootData && ob) {
		ob.vmCount++;
	}
	return ob
}
